﻿using System;
using System.Linq.Expressions;
using FluentlyXml.Core.Deserialization;
using FluentlyXml.Core.Deserialization.BuiltInDeserializers;

namespace FluentlyXml.Core.DSL
{
	/// <summary> </summary>
	internal class TypeDeserializationSpec<T> : ITypeDeserializationSpec<T>
	{
		private readonly IDeserializationConfig _config;

		public TypeDeserializationSpec(IDeserializationConfig config)
		{
			_config = config;
		}

		/// <summary> </summary>
		public ITypeDeserializationSpec<T> DetermineIdentityBy(Func<T, object> identitySelector)
		{
			//Selector must be converted for use with the Reflection-based core deserialization process. 
			Func<object, object> wrappedSelector = o => identitySelector((T)o);
			_config.SetIdentityFunction(typeof(T), wrappedSelector);
			return this;
		}

		/// <summary> </summary>
		public ITypeDeserializationSpec<T> Ignore(Expression<Func<T, object>> expression)
		{
			_config.SetPropertyDeserializer(typeof (T), expression.GetProperty(), DeserializationBehaviors.Ignore);
			return this;
		}

		/// <summary> </summary>
		public IPropertyDeserializationSpec<T> Deserialize(Expression<Func<T, object>> expression)
		{
			return new PropertyDeserializationSpec<T>(expression, _config);
		}

		public ITypeDeserializationSpec<T> AfterDeserialization(Action<T> callback)
		{
			_config.AddPostDeserializationCallback(typeof(T), o => callback((T)o));
			return this;
		}
	}
}